package com.zodiac.alioth.common.util;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * okHttp调用工具
 *
 * @author: zhzh
 * @date: 2021/7/9 11:27 上午
 */
@Slf4j
public class OkHttpUtil {

    static ConnectionPool connectionPool = new ConnectionPool(200, 5, TimeUnit.SECONDS);

    private static OkHttpClient okHttpClient;

    static {
        okHttpClient = initDefault();
    }

    public static OkHttpClient getOkHttpClient() {
        return okHttpClient;
    }

    private static OkHttpClient initDefault() {
        return initOkHttpClient(1000, 1000, 1000, connectionPool);
    }

    /**
     * 初始化client
     *
     * @param readTimeout    readTimeout
     * @param connectTimeout connectTimeout
     * @param writeTimeout   writeTimeout
     * @param connectionPool connectionPool
     * @return OkHttpClient
     */
    public static OkHttpClient initOkHttpClient(int readTimeout, int connectTimeout, int writeTimeout, ConnectionPool connectionPool) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectionPool(connectionPool);
        builder.readTimeout(readTimeout, TimeUnit.MILLISECONDS);
        builder.connectTimeout(connectTimeout, TimeUnit.MILLISECONDS);
        builder.writeTimeout(writeTimeout, TimeUnit.MILLISECONDS);
        // 协议
        List<Protocol> protocols = new ArrayList<>();
        protocols.add(Protocol.HTTP_1_1);
        protocols.add(Protocol.HTTP_2);
        builder.protocols(protocols);
        okHttpClient = builder.build();
        return okHttpClient;
    }


    public static void main(String[] args) throws InterruptedException {
        long start = System.currentTimeMillis();
        post4JsonAsync("https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=asdf&json=1", new JSONObject());

        for (int i = 0; i < 1000; i++) {
            post4JsonAsync("https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=" + i, new JSONObject());
        }
        System.out.println(System.currentTimeMillis() - start);
        System.out.println("---");

    }

    /**
     * 默认调用方法
     * 异步调用
     *
     * @param url  请求地址
     * @param json 请求body[json]
     */
    public static void post4JsonAsync(String url, JSONObject json) {
        try {
            // 1 获取OkHttpClient对象
            OkHttpClient client = Objects.isNull(okHttpClient) ? initDefault() : okHttpClient;
            // 2 构建参数
            RequestBody requestBody = RequestBody.create(JSONObject.toJSONString(json), MediaType.parse("application/json; charset=utf-8"));
            // 3 构建 request
            Request request = new Request.Builder()
                    .url(url)
                    .post(requestBody)
                    .build();
            // 4 将Request封装为Call
            Call call = client.newCall(request);
            // 5 异步调用
            call.enqueue(new Callback() {
                @Override
                public void onFailure(@NotNull Call call, IOException e) {
                    log.warn("postForJsonAsync failure, call={}", call, e);
                }

                @Override
                public void onResponse(@NotNull Call call, @NotNull final Response response) throws IOException {
                    log.debug("postForJsonAsync success, call={}, response={}", call.request(), response);
                    response.close();
                }
            });
        } catch (Exception e) {
            log.error("OkHttpUtil error, url={}, json={}", url, json, e);
        }
    }

    /**
     * 默认调用方法
     * 异步调用
     *
     * @param url  请求地址
     * @param json 请求body[json]
     */
    public static String post4Json(String url, JSONObject json) {
        String responseBody = null;
        try {
            // 1 获取OkHttpClient对象
            OkHttpClient client = Objects.isNull(okHttpClient) ? initDefault() : okHttpClient;
            // 2 构建参数
            RequestBody requestBody = RequestBody.create(JSONObject.toJSONString(json), MediaType.parse("application/json; charset=utf-8"));
            // 3 构建 request
            Request request = new Request.Builder()
                    .url(url)
                    .post(requestBody)
                    .build();
            // 4 同步调用
            Response response = client.newCall(request).execute();
            int status = response.code();
            if (response.isSuccessful()) {
                responseBody = Objects.requireNonNull(response.body()).string();
            }
        } catch (Exception e) {
            log.error("OkHttpUtil error, url={}, json={}", url, json, e);
        }
        return responseBody;
    }

    /**
     * get
     *
     * @param url     请求的url
     * @param queries 请求的参数，在浏览器？后面的数据，没有可以传null
     * @return
     */
    public static String get(String url, Map<String, String> queries) {
        OkHttpClient client = Objects.isNull(okHttpClient) ? initDefault() : okHttpClient;
        String responseBody = "";
        StringBuilder sb = new StringBuilder(url);
        if (queries != null && queries.keySet().size() > 0) {
            boolean firstFlag = true;
            for (Map.Entry<String, String> entry : queries.entrySet()) {
                if (firstFlag) {
                    sb.append("?").append(entry.getKey()).append("=").append(entry.getValue());
                    firstFlag = false;
                } else {
                    sb.append("&").append(entry.getKey()).append("=").append(entry.getValue());
                }
            }
        }
        Request request = new Request.Builder()
                .url(sb.toString())
                .build();
        try (Response response = client.newCall(request).execute()) {
            int status = response.code();
            if (response.isSuccessful()) {
                return Objects.requireNonNull(response.body()).string();
            }
        } catch (Exception e) {
            log.error("okhttp3 put error >> ex = {}", ExceptionUtils.getStackTrace(e));
        }
        return responseBody;
    }


    /**
     * get
     *
     * @param url     请求的url
     * @param queries 请求的参数，在浏览器？后面的数据，没有可以传null
     * @return
     */
    public static String getForHeader(String url, Map<String, String> queries) {
        String responseBody = "";
        StringBuffer sb = new StringBuffer(url);
        if (queries != null && queries.keySet().size() > 0) {
            boolean firstFlag = true;
            Iterator iterator = queries.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry<String, String>) iterator.next();
                if (firstFlag) {
                    sb.append("?" + entry.getKey() + "=" + entry.getValue());
                    firstFlag = false;
                } else {
                    sb.append("&" + entry.getKey() + "=" + entry.getValue());
                }
            }
        }
        Request request = new Request.Builder()
                .addHeader("key", "value")
                .url(sb.toString())
                .build();
        Response response = null;
        try {
            response = okHttpClient.newCall(request).execute();
            int status = response.code();
            if (response.isSuccessful()) {
                return response.body().string();
            }
        } catch (Exception e) {
            log.error("okhttp3 put error >> ex = {}", ExceptionUtils.getStackTrace(e));
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return responseBody;
    }

    /**
     * Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"}
     * 参数一：请求Url
     * 参数二：请求的JSON
     * 参数三：请求回调
     */
    public static String postJsonParams(String url, String jsonParams) {
        String responseBody = "";
        RequestBody requestBody = RequestBody.create(jsonParams, MediaType.parse("application/json; charset=utf-8"));
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        Response response = null;
        try {
            response = okHttpClient.newCall(request).execute();
            int status = response.code();
            if (response.isSuccessful()) {
                return response.body().string();
            }
        } catch (Exception e) {
            log.error("okhttp3 post error >> ex = {}", ExceptionUtils.getStackTrace(e));
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return responseBody;
    }

    /**
     * Post请求发送xml数据....
     * 参数一：请求Url
     * 参数二：请求的xmlString
     * 参数三：请求回调
     */
    public static String postXmlParams(String url, String xml) {
        String responseBody = "";
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml);
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        Response response = null;
        try {
            response = okHttpClient.newCall(request).execute();
            int status = response.code();
            if (response.isSuccessful()) {
                return response.body().string();
            }
        } catch (Exception e) {
            log.error("okhttp3 post error >> ex = {}", ExceptionUtils.getStackTrace(e));
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return responseBody;
    }
}
